﻿using log4net;
using log4net.Core;
using Microsoft.Extensions.Logging;
using System;


namespace CNative.Logging.Log4Net
{
    public class Log4NetLogger : Microsoft.Extensions.Logging.ILogger
    {
        private readonly log4net.ILog _log;
        private readonly Log4NetProviderOptions _options;
        public string Name => _log.Logger.Name;
        public Log4NetLogger() : this(new Log4NetProviderOptions())
        {

        }
        public Log4NetLogger(Log4NetProviderOptions options)
        {
            _options = options;
            _log = LogManager.GetLogger(options.LoggerRepositoryName, options.Name);
        }

        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }

        /// <summary>判断是否开启记录
        /// </summary>
        public bool IsEnabled(LogLevel logLevel)
        {
            var convertLogLevel = ConvertLogLevel(logLevel);
            return _log.Logger.IsEnabledFor(convertLogLevel);
        }


        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }

            var message = formatter(state, exception);

            if (!string.IsNullOrEmpty(message) || exception != null)
            {

                switch (logLevel)
                {
                    case LogLevel.Critical:
                        _log.Fatal(message);
                        break;
                    case LogLevel.Debug:
                        _log.Debug(message);
                        break;
                    case LogLevel.Trace:
                        //Console.WriteLine(message);
                        _log.Debug(message);
                        break;
                    case LogLevel.Error:
                        _log.Error(message);
                        break;
                    case LogLevel.Information:
                        _log.Info(message);
                        break;
                    case LogLevel.Warning:
                        _log.Warn(message);
                        break;
                    default:
                        _log.Info(message);
                        break;
                }
            }

            //var builder = new System.Text.StringBuilder();
            //builder.Append(DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss.fff zzz"));
            //builder.Append(" [");
            //builder.Append(logLevel.ToString());
            //builder.Append("] ");
            //builder.Append(_options.Name);
            //builder.Append(": ");
            //builder.AppendLine(message);

            //if (exception != null)
            //{
            //    builder.AppendLine(exception.ToString());
            //}
            //Write(AppContext.BaseDirectory + "log\\" + DateTime.Now.ToString("yyyyMMdd") + ".txt", builder.ToString());
        }
        public Level ConvertLogLevel(LogLevel logLevel)
        {
            switch (logLevel)
            {
                case LogLevel.Trace:
                    return Level.Trace;
                case LogLevel.Debug:
                    return Level.Debug;
                case LogLevel.Information:
                    return Level.Info;
                case LogLevel.Warning:
                    return Level.Warn;
                case LogLevel.Error:
                    return Level.Error;
                case LogLevel.Critical:
                    return Level.Fatal;
                case LogLevel.None:
                    return Level.Off;
                default:
                    return Level.Debug;
            }
        }


        object lockobj = new object();
        /// <summary>
        /// 写入文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="content"></param>
        public void Write(string path, string content)
        {
            lock (lockobj)
            {
                var pat = System.IO.Path.GetDirectoryName(path);
                if (!System.IO.Directory.Exists(pat)) System.IO.Directory.CreateDirectory(pat);

                var fs = new System.IO.FileStream(path, System.IO.File.Exists(path) ? System.IO.FileMode.Append : System.IO.FileMode.OpenOrCreate);
                var sw = new System.IO.StreamWriter(fs);
                //开始写入
                sw.Write(content);
                //清空缓冲区
                sw.Flush();
                //关闭流
                sw.Close();
                fs.Close();
            }
        }

    }
}
